package com.topisv.tms.service.base;

import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springside.modules.persistence.DynamicSpecifications;
import org.springside.modules.persistence.SearchFilter;

import com.topisv.tms.entity.QueryParamHolder;
import com.topisv.tms.service.account.ShiroDbRealm.ShiroUser;
import com.topisv.tms.utils.enums.DataTableEnums;

/**
 * service层的基类,将共有的查询抽取出来
 *  Date          Author       Version       Description
 * ----------------------------------------------------------
 *  2014-8-8      CC            1.0           Create
 */
public class BaseService {
	protected Logger log = LoggerFactory.getLogger(getClass());
	/**
	 * 分页查询
	 * @param paramHolder
	 * @param executor
	 * @param clazz
	 * @return Page<T>
	 */
	public <T> Page<T> findByJson(QueryParamHolder paramHolder, JpaSpecificationExecutor<T> executor, Class<T> clazz) {
		return findByJson(paramHolder, executor, null, clazz);
	}

	/**
	 * 分页查询
	 * @param paramHolder
	 * @param executor
	 * @param spec
	 * @param clazz
	 * @return Page<T>
	 */
	public <T> Page<T> findByJson(QueryParamHolder paramHolder, JpaSpecificationExecutor<T> executor, Specification<T> spec, Class<T> clazz) {
		PageRequest pageRequest = buildPageRequest(paramHolder.getCurPage(), paramHolder.getPageSize(), findSortCol(paramHolder));
		if (spec == null) {
			spec = buildSpecification(paramHolder.getSearchParams(), clazz);
		}
		return executor.findAll(spec, pageRequest);
	}

	/**
	 * 查找排序列
	 * @param paramHolder
	 * @return String
	 */
	public String findSortCol(QueryParamHolder paramHolder) {
		Map<String, String> paramMap = paramHolder.getParamMap();
		if (paramMap != null) {
			String sortColIndex = paramMap.get(DataTableEnums.SORT_COL.getValue());
			if (!StringUtils.isBlank(sortColIndex)) {
				String sortCol = paramMap.get(DataTableEnums.COL_PREFIX.getValue() + sortColIndex);
				if (!StringUtils.isBlank(sortCol)) {
					String sortType = paramMap.get(DataTableEnums.SORT_DIR.getValue());
					return sortCol + DataTableEnums.CONNECTOR.getValue() + (sortType == null ? DataTableEnums.SORT_ASC.getValue() : sortType);
				}
			}
		}
		return null;
	}

	/**
	 * 创建分页请求.
	 */
	public PageRequest buildPageRequest(int pageNumber, int pagzSize, String sortType) {
		Sort sort = null;
		if (StringUtils.isBlank(sortType) || DataTableEnums.SORT_AUTO.getValue().equalsIgnoreCase(sortType)) {
			sort = new Sort(Direction.DESC, "id");
		} else {
			String[] sorts = sortType.split(DataTableEnums.CONNECTOR.getValue());
			if (sortType.toLowerCase().endsWith(DataTableEnums.SORT_DESC.getValue())) {
				sort = new Sort(Direction.DESC, sorts[0]);
			} else if (sortType.toLowerCase().endsWith(DataTableEnums.SORT_ASC.getValue())) {
				sort = new Sort(Direction.ASC, sorts[0]);
			} else {
				sort = new Sort(Direction.ASC, sorts[0]);
			}
		}
		return new PageRequest(pageNumber - 1, pagzSize, sort);
	}

	public <T> Page<T> findByParam(Map<String, Object> filterParams, int pageNumber, int pagzSize, String sortType, JpaSpecificationExecutor<T> executor, Class<T> clazz) {
		PageRequest pageRequest = buildPageRequest(pageNumber, pagzSize, sortType);
		Specification<T> specification = buildSpecification(filterParams, clazz);
		return executor.findAll(specification, pageRequest);
	}

	/**
	 * 创建动态查询条件组合.
	 */
	public <T> Specification<T> buildSpecification(Map<String, Object> filterParams, Class<T> clazz) {
		Map<String, SearchFilter> filters = SearchFilter.parse(filterParams);
		Specification<T> spec = DynamicSpecifications.bySearchFilter(filters.values(), clazz);
		return spec;
	}

	public ShiroUser getShiroUser() {
		return (ShiroUser) SecurityUtils.getSubject().getPrincipal();
	}
}
